package cn.ycc1.springioc;

import cn.ycc1.springioc.bean.Car;
import cn.ycc1.springioc.bean.Person;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 1. 追源码的时候，先放行看在哪能获取到参数就在哪打断点
 * 2. spring创建bean的三级缓存机制 成品区，半成品区，objectFactory, 解决循环依赖
 * 解决不了的问题采用代理的思想
 * 3. 创建bean的源码追踪
 *
 * 获取单实例
 * @see \org\springframework\spring-beans\6.0.7\spring-beans-6.0.7.jar!\org\springframework\beans\factory\support\DefaultSingletonBeanRegistry.class
 * @Nullable
 *     protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 *         Object singletonObject = this.singletonObjects.get(beanName);
 *         if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
 *             singletonObject = this.earlySingletonObjects.get(beanName);
 *             if (singletonObject == null && allowEarlyReference) {
 *                 synchronized(this.singletonObjects) {
 *                     singletonObject = this.singletonObjects.get(beanName);
 *                     if (singletonObject == null) {
 *                         singletonObject = this.earlySingletonObjects.get(beanName);
 *                         if (singletonObject == null) {
 *                             ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
 *                             if (singletonFactory != null) {
 *                                 singletonObject = singletonFactory.getObject();
 *                                 this.earlySingletonObjects.put(beanName, singletonObject);
 *                                 this.singletonFactories.remove(beanName);
 *                             }
 *                         }
 *                     }
 *                 }
 *             }
 *         }
 *
 *         return singletonObject;
 *     }
 */
@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(SpringIocApplication.class, args);
        System.out.println("===============ioc容器创建完成================");

        // 获取容器中的beans
        Person person = ioc.getBean(Person.class);
        System.out.println("运行：" + person);
    }

    public static void test(String[] args) {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
        // 获取容器中的beans
        Person person = ioc.getBean(Person.class);
        System.out.println("运行：" + person);
    }

    public static void test1(String[] args) {

        ConfigurableApplicationContext ioc = SpringApplication.run(SpringIocApplication.class, args);
        // System.out.println(ioc);
        System.out.println("===============ioc容器创建完成================");

//        String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
//        // 获取容器中的beans
//        for (String beanDefinitionName : beanDefinitionNames) {
//            System.out.println(beanDefinitionName);
//        }
        Car bean1 = ioc.getBean(Car.class);
        System.out.println(bean1);
        Car bean2 = ioc.getBean(Car.class);
        System.out.println(bean1 == bean2); // true

        Map<String, Car> beansOfType = ioc.getBeansOfType(Car.class);
        System.out.println("beansOfType = " + beansOfType);

    }

}
